package com.lb.uts.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lb.uts.annotation.Modify;
import com.lb.uts.constants.UTSConstants;
import com.lb.uts.entity.JobExecuteRecord;
import com.lb.uts.entity.JobSearch;
import com.lb.uts.entity.ScheduleJob;
import com.lb.uts.mapper.JobExecuteRecordMapper;
import com.lb.uts.service.AbstractBaseService;
import com.lb.uts.service.IActiveClientService;
import com.lb.uts.service.IJobRecordService;
import com.lb.uts.service.IScheduleJobService;
import com.lb.uts.service.manager.SchedulerManager;
import com.lb.uts.util.IdUtils;
import com.lb.uts.util.PolicyUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 执行记录
 *
 * @author liangb
 * @version 3.0
 * @date 2019/4/26 17:35
 */
@Service
public class JobRecordService extends AbstractBaseService<JobExecuteRecordMapper, JobExecuteRecord> implements IJobRecordService {

    private Logger logger = LoggerFactory.getLogger(JobRecordService.class);
    @Autowired
    private JobExecuteRecordMapper jobExecuteRecordMapper;

    @Autowired
    private SchedulerManager schedulerManager;

    @Autowired
    private IScheduleJobService scheduleJobService;

    @Value("${server.port}")
    private String port;

    public JobExecuteRecord insertJobExecuteRecord(ScheduleJob job, String executeResult, String host) {
        JobExecuteRecord record = new JobExecuteRecord();
        record.setId(IdUtils.nextUUID());
        record.setJobId(job.getJobId());
        record.setStartTime(LocalDateTime.now());
        record.setCallStatus(executeResult);
        record.setIp(host);
        String exeIp = null;
        try {
            exeIp = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {

        }
        if (host == null) {
            record.setErrorMsg("没有合适的执行器");
            record.setCallStatus(UTSConstants.REMOTECALL_STATUS_CALL_FAIL);
        }
        record.setExeIp(exeIp == null ? "" : exeIp + ":" + port);
        int num = jobExecuteRecordMapper.insert(record);
        if (num == 1) {
            return host == null ? null : record;
        }
        logger.info("插入调用记录数据失败,调用参数:job=" + job + ",调用状态:" + executeResult);
        return null;
    }

    public int countJobRecordNum(String jobId, String status) {
        return jobExecuteRecordMapper.countJobRecordNum(jobId, status);
    }

    public PageInfo<JobExecuteRecord> queryList(int pageNo, int pageSize, String status, JobSearch jobSearch) {
        PageHelper.startPage(pageNo, pageSize);
        List<JobExecuteRecord> scheduleJobList = jobExecuteRecordMapper.queryByStatus(status, jobSearch);
        PageInfo<JobExecuteRecord> page = new PageInfo<>(scheduleJobList);
        page.setPageNum(pageNo);
        page.setPageSize(pageSize);
        return page;
    }

    @Override
    @Modify
    public void updateFailRecord(String systemName, String host, String jobRecordId, String e) {
        JobExecuteRecord jobExecuteRecord = jobExecuteRecordMapper.selectById(jobRecordId);
        jobExecuteRecord.setCallStatus(UTSConstants.REMOTECALL_STATUS_CALL_FAIL);
        jobExecuteRecord.setEndTime(LocalDateTime.now());
        jobExecuteRecord.setErrorMsg(e);
        int num = jobExecuteRecordMapper.updateById(jobExecuteRecord);
        String jobId = jobExecuteRecord.getJobId();
        ScheduleJob scheduleJob = PolicyUtil.getById(jobId);
        boolean checkExists = schedulerManager.checkExists(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        if (!checkExists) {
            num = scheduleJobService.updateStatus(scheduleJob);
        }
        Integer concurrentNum = scheduleJob.getConcurrentNum();
        if ("01".equals(scheduleJob.getSlave())) {
            //多台执行
            ScheduleJob inDb = scheduleJobService.getById(jobId);
            num = scheduleJobService.updateRunNum(jobId, (inDb.getRunNum() == 1 ? "true" : null), concurrentNum, -1);
        } else {
            if (concurrentNum > 0) {
                if (host != null || (host == null && systemName == null)) {
                    num = scheduleJobService.updateRedRunNum(jobId, null, concurrentNum);
                }
            } else {
                num = scheduleJobService.updateRunNum(jobId, null, concurrentNum, -1);
            }
        }
        //发送警告邮件
        String emails = scheduleJob.getAlarmEmail();
        if (StringUtils.isNotBlank(emails)) {
            logger.info("定时任务执行失败通知开始");
            try {
                //TODO:发送邮件
            } catch (Exception ex) {
                logger.error("定时任务执行失败通知：" + ex);
            }
        }
        if (num <= 0) {
            logger.error("异常执行记录更新失败");
        }
        PolicyUtil.updateActiveInfo(systemName, host);
    }

    @Override
    public void updateSuccessRecord(String systemName, String status, String host, String jobRecordId, String result) {
        JobExecuteRecord jobExecuteRecord = jobExecuteRecordMapper.selectById(jobRecordId);
        jobExecuteRecord.setCallStatus(status);
        jobExecuteRecord.setEndTime(LocalDateTime.now());
        jobExecuteRecord.setResponseContent(result);
        jobExecuteRecordMapper.updateById(jobExecuteRecord);
        String jobId = jobExecuteRecord.getJobId();
        ScheduleJob scheduleJob = PolicyUtil.getById(jobId);
        boolean checkExists = schedulerManager.checkExists(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        if (!checkExists) {
            scheduleJobService.updateStatus(scheduleJob);
        }
        Integer concurrentNum = scheduleJob.getConcurrentNum();
        int num = 0;
        if ("01".equals(scheduleJob.getSlave())) {
            //多台执行
            ScheduleJob inDb = scheduleJobService.getById(jobId);
            num = scheduleJobService.updateRunNum(jobId, (inDb.getRunNum() == 1 ? "true" : null), concurrentNum, -1);
        } else {
            if (concurrentNum > 0) {
                num = scheduleJobService.updateRedRunNum(jobId, null, concurrentNum);
            } else {
                num = scheduleJobService.updateRunNum(jobId, null, concurrentNum, -1);
            }
        }
        if (num <= 0) {
            logger.error("正常执行记录更新失败");
        }
        PolicyUtil.updateSuccessActiveInfo(systemName, host);
    }
}
